#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LEN 20
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10       // 最大📚量
char * s_gets(char * st, int n);

int count = 0;

struct book {
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

char get_choice(void);      // 获取用户选择
void add(struct book *);    // 添加一本书
void change(struct book *); // 替换一本书
void del(struct book *);    // 删除一本书
void print(struct book *);   // 打印书单
void write_file(struct book *, char *); // 将数据写入文件

int main(void) {
    char name[LEN];
    struct book library[MAXBKS];
    char ch;
    FILE *fp;

    // 打开文件并读取其中内容到结构体
    printf("Please input the file name: ");
    s_gets(name, LEN);
    if ((fp = fopen(name, "a+b")) == NULL) {
        fprintf(stderr, "Can't open %s", name);
        exit(EXIT_FAILURE);
    }
    rewind(fp); // 使文件指针位于文件开始处   因为 "a+b"
    while (count < MAXBKS && fread(&library[count], sizeof(struct book), 1, fp) == 1)
        count++;        // 当前的 book 数
    fclose(fp);

    // 打印文件中已有的数据
    printf("There are %d books:\n", count);
    print(library);

    // 让用户输入选项
    while ((ch = get_choice()) != 'q')
    {
        switch (ch) {
            case 'a':
                add(library);
                break;
            case 'c':
                change(library);
                break;
            case 'd':
                del(library);
                break;
            case 'p':
                print(library);
                break;
            default:
                printf("Program error.\n");
                break;
        }
    }

    // 将数据输入至文件中
    write_file(library, name);

    return 0;
}

char get_choice(void)
{
    char ch;
    printf("Please input your choice:\n");
    printf("a. add some books        c. change a book\n");
    printf("d. delete a book         p. print all books\n");
    printf("q. quit.\n");
    while ((ch = getchar()) != 'a' && ch != 'c' && ch != 'd' && ch != 'p' && ch != 'q')
    {
        while (getchar() != '\n') continue;
        printf("Please input the right character.\n");
    }
    while (getchar() != '\n') continue;

    return ch;
}

void add(struct book * ps)
{
    if (count == MAXBKS)
        printf("Sorry, the list if full.\n");
    else
    {
        printf("Please input the title （empty line to quit):\n");
        while (count < MAXBKS && s_gets(ps[count].title, MAXTITL) != NULL && ps[count].title[0] != '\0')
        {
            printf("Input the author:\n");
            s_gets(ps[count].author, MAXAUTL);
            printf("Input the value:\n");
            scanf("%f", &ps[count].value);
            while (getchar() != '\n') continue;
            printf("Now, next title (empty line to quit):\n");
            count++;
        }
    }
}

void change(struct book * ps)
{
    int i;
    char name[MAXTITL];

    if (count == 0)
        printf("Sorry, the list is empty.\n");
    else
    {
        printf("Please input the title of book you want to change:\n");
        s_gets(name, MAXTITL);
        for (i = 0; i < count; i++)
        {
            if (!strcmp(name, ps[i].title))  // 找到了
            {
                printf("Please input the title of new book:\n");
                s_gets(ps[i].title, MAXTITL);
                printf("Input the author:\n");
                s_gets(ps[i].author, MAXAUTL);
                printf("Input the value:\n");
                scanf("%f", &ps[i].value);
                while (getchar() != '\n') continue;
                break;
            }
        }
        if (i == count)
            printf("Sorry, we can't find the book you input.\n");
    }
}

void del(struct book * ps)
{
    char name[MAXTITL];
    int i, j;

    if (count == 0)
        printf("Sorry, the list is empty.\n");
    printf("Please input the title of book you want to delete:\n");
    s_gets(name, MAXAUTL);
    for (i = 0; i < count; i++)
    {
        if (!strcmp(name, ps[i].title))     // 对比成功时的 i
        {
            for (j = i + 1; j < count; j++)  // ***
                ps[j - 1] = ps[j];
            count--;
            strcpy(ps[count].title, "");    // 最后一个元素就空了
            strcpy(ps[count].author, "");
            ps[count].value = 0;
            break;
        }
    }
    if (i == count)
        printf("Sorry, we can't find the book you input.\n");
}

void print(struct book * ps)
{
    int i;

    for (i = 0; i < count; i++)
        printf("%s by %s: $%.2f\n", ps[i].title, ps[i].author, ps[i].value);
}

void write_file(struct book * ps, char * st)
{
    FILE * fp;

    fp = fopen(st, "w+b");
    fwrite(ps, sizeof(struct book), count, fp);
    fclose(fp);
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;

    ret_val = fgets(st, n , stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');
        if (find)
            *find = '\0';
        else
            while (getchar() != '\n') continue;
    }

    return ret_val;
}


// a+b 和 w+b 的区别
// w+b 以二进制格式打开文件，若文件存在则文件中的内容清零
// a+b 以二进制格式打开文件，以追加到末尾的形式添加数据